/**
 * 通用翻页控件，需要 bootstrap 3 和 jQuery 3+
 *
 * html:
 * <pre>
 <ul data-page-no="1" data-page-size="10" data-total-page="5" class="pagination" style="float:right;">
     <li><a data-role="prev">«</a></li>
     <li class="active"><a data-page-no="1" data-active="true">1</a></li>
     <li><a data-page-no="2" data-role="normal">2</a></li>
     <li><a data-page-no="3" data-role="normal">3</a></li>
     <li><a data-page-no="4" data-role="normal">4</a></li>
     <li><a data-page-no="5" data-role="normal">5</a></li>
     <li><a data-role="next">»</a></li>
 </ul>
 </pre>
 * 事件：
 * <pre>
 * $('.pagination').on ('pagination', function (p) {
 *     console.log ('this = ', this);
 *     console.log ('from = ' + p.from);
 *     console.log ('to   = ' + p.to);
 *     console.log ('size = ' + p.size);
 * });
 * </pre>
 */
(function ($) {
    if ($.fn.pagination) return;
    var _DEFAULT_LANG = 'zh_CN';

    function invoke (_top, pagination, options, params) {
        var events, a, i, r, target;
        if (options && 'onpagination' in options && typeof options['onpagination'] === 'function') {
            r = options['onpagination'].apply (this, [{from:params[0],to:params[1],size:pagination.pageSize}]);
        } else if (_top && _top.length) {
            events = $._data (_top [0]);
            if (events && ('events' in events) && ('pagination' in (events = events ['events']))) {
                a = events['pagination'];
                if (a.length) {
                    for (i = 0; i < a.length; i ++) {
                        if (a[i].handler) {
                            if (a[i].data) {
                                params.push (a[i].data);
                            }
                            r = a[i].handler.apply (_top, [{from:params[0],to:params[1],size:pagination.pageSize}]);
                            break;
                        }
                    }
                }
            }
        }

        if (r !== false) {
            target = params[1];
            _top.find ('li.active').removeClass ('active');
            _top.find ('a[data-active=true]').attr ({'data-active':false,'data-role':'normal'});
            _top.find ('a[data-page-no=' + target + ']').attr ('data-active', true);
            _top.closest ('.pagination-panel').find ('.pagination-info').remove ();
            _top.removeData ('pagination-init');
            if (target > 1) {
                _top.find ('a[data-role=fake]:first').attr ('data-role', 'prev').removeClass ('disabled-page-handler');
            } else if (target < pagination.totalPages) {
                _top.find ('a[data-role=fake]:last').attr ('data-role', 'next').removeClass ('disabled-page-handler');
            }
            _top.attr ('data-page-no', target);
            pagination.pageNo = target;

            init_pagination (_top);
        }
    }

    function on_page_handler_clicked (_top, pagination) {
        var target = $(this).attr ('data-page-no'), options = _top.data ('settings');
        if (target !== '') {
            target = parseInt (target, 10);
        }

        invoke (_top, pagination, options, [pagination.pageNo, target]);
    }

    function _move (_top, pagination, dir) {
        if ($(this).hasClass ('disabled-page-handler')) {
            return;
        }
        var target = (dir === 'prev') ? (pagination.pageNo - 1) : (pagination.pageNo + 1),
            options = _top.data ('settings');

        invoke (_top, pagination, options, [pagination.pageNo, target]);
    }

    function init_pagination (self, options) {
/*
        if (self.data ('pagination-init')) {
            return;
        }
*/
        console.debug ('init pagination');
        options = options || self.data ('settings');
        var parent, text, lang = options ['lang'] || _DEFAULT_LANG, res, rpm = {
            'page-no'    : parseInt (self.attr ('data-page-no')),
            'page-size'  : parseInt (self.attr ('data-page-size')),
            'total-page' : parseInt (self.attr ('data-total-page'))
        }, info = {
            pageNo:rpm['page-no'],
            pageSize:rpm['page-size'],
            totalPages:rpm['total-page']
        };

        res = $.fn.pagination.RESOURCES[lang] || $.fn.pagination.RESOURCES[_DEFAULT_LANG];
        text = res.LABEL.replace (/\${(.*?)}/g, function (key) {
            key = key.substr(2, key.length - 3);
            return rpm [key];
        });
        if (rpm ['page-no'] === 1) {
            self.find ('a[data-role=prev]').attr ('data-role', 'fake');
        } else {
            self.find ('a[data-role=prev]').off ('click').on ('click', function () {
                _move.apply (this, [self, info, 'prev']);
            });
        }
        if (rpm ['total-page'] === rpm ['page-no']) {
            self.find ('a[data-role=next]').attr ('data-role', 'fake');
        } else {
            self.find ('a[data-role=next]').off ('click').on ('click', function () {
                _move.apply (this, [self, info, 'next']);
            });
        }

        // patching the page handler view
        self.find ('a[data-role]').each (function () {
            var self=$(this), role=self.attr ('data-role'),active=self.attr ('data-active');
            if (role === 'fake') {
                self.addClass ('disabled-page-handler');
            } else if (active === 'true') {
                self.closest ('li').addClass ('active');
                self.removeAttr ('data-role');
            } else if (role === 'prev') {
                self.attr ('title', res ['prev']);
            } else if (role === 'next') {
                self.attr ('title', res ['next']);
            }
        });
        self.find ('a[data-role=normal]').off ('click').on ('click', function () {
            // on_page_handler_clicked ();
            on_page_handler_clicked.apply (this, [self, info]);
        });

        // build the left panel
        parent = self.closest ('.pagination-panel');
        if (!parent || !parent.length) {
            parent = $('<div class="pagination-panel clearfix"/>');
            self.after (parent);
            self.appendTo (parent);
        }

        var p_info = parent.find ('.pagination-info');
        if (p_info && p_info.length) {
            p_info.remove ();
        }
        parent.prepend ($('<div class="pagination-info"/>').text (text));
        self.data ('pagination-init', true);
    }

    $.fn.pagination = function (options) {
        return this.each (function () {
            var self = $(this), settings = self.data ('settings') || {lang:_DEFAULT_LANG};
            if (options) {
                $.extend (settings, options);
            }
            self.data ('settings', settings);

            if (!self.data ('pagination-init') || (options && options ['lang'])) {
                init_pagination (self, settings);
            }
        });
    };

    $.fn.pagination.RESOURCES = {
        'zh_CN' : {
            LABEL : '共${page-no}/${total-page}页, 每页${page-size}条',
            next  : '下一页',
            prev  : '上一页'
        },
        'en_US' : {
            LABEL : 'Total ${page-no}/${total-page} Pages, ${page-size} rows/Page',
            next  : 'Next',
            prev  : 'Previous'
        }
    };
})(jQuery);
$(function () {
    $('.pagination').pagination ();
});